package p.sglmsn.top.apale;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.StrUtil;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.control.Button;
import javafx.scene.control.TextField;
import javafx.scene.input.Dragboard;
import javafx.scene.input.TransferMode;
import javafx.scene.layout.VBox;
import javafx.stage.FileChooser;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.List;

public class DecryptTabController {
    @FXML
    private TextField sourceFileField;

    @FXML
    private TextField targetFileField;

    @FXML
    private Button decryptBrowseButton;

    @FXML
    private Button decryptButton;

    @FXML
    private VBox decryptBox;


    List<File> files = null;

    @FXML
    private void initialize() {
        // 添加拖拽支持
        setupDragAndDrop();
    }

    @FXML
    private void browseSourceFile(ActionEvent event) {
        FileChooser fileChooser = new FileChooser();
        fileChooser.setTitle("选择要解密的文件");
        fileChooser.getExtensionFilters().add(new FileChooser.ExtensionFilter("加密文件", "*.*"));

        File file = fileChooser.showOpenDialog(decryptBrowseButton.getScene().getWindow());
        if (file != null) {
            sourceFileField.setText(file.getAbsolutePath());
        }
    }

    @FXML
    private void decryptFile(ActionEvent event) {
        String sourcePath = sourceFileField.getText();
        if (files == null) {
            if (StrUtil.isBlank(sourcePath)) {
                System.out.println("源文件不存在");
                return;
            }

            File file = new File(sourcePath);
            files = List.of(file);
        }
        String targetPath = targetFileField.getText();


        try {
            for (File file : files) {
                if (file.isDirectory()) {
                    List<File> files1 = FileUtil.loopFiles(file, pathname -> pathname.getName().endsWith(".jpg"));
                    for (File file1 : files1) {
                        decryptFileWithImage(file1, targetPath);
                    }
                }else{
                    decryptFileWithImage(file, targetPath);
                }
            }
        } catch (IOException e) {
            System.out.println("解密失败: " + e.getMessage());
            e.printStackTrace();
        }


        File sourceFile = new File(sourcePath);
        if (!sourceFile.exists()) {
            System.out.println("源文件不存在");
            return;
        }

        try {
            decryptFileWithImage(sourceFile, targetPath);
            System.out.println("解密成功完成");
        } catch (Exception e) {
            System.out.println("解密失败: " + e.getMessage());
            e.printStackTrace();
        }
    }

    /**
     * 从合并文件中提取原始ZIP文件（根据ZIP文件头来识别并跳过图片部分）
     *
     * @param sourceFile 合并后的文件
     * @param targetFile 提取的原始ZIP文件
     * @throws IOException IO异常
     */
    private void decryptFileWithImage(File sourceFile, String targetFile) throws IOException {
        File f;
        if (StrUtil.isBlank(targetFile)) {
            File parentFile = sourceFile.getParentFile();
            File zip = new File(parentFile, "zip");
            zip.mkdirs();
            f = new File(zip, sourceFile.getName().substring(0,sourceFile.getName().length()-4));
        } else {
            f = new File(targetFile);
        }
        HelloApplication application = (HelloApplication) decryptBrowseButton.getScene().getWindow().getUserData();
        ImageTabController imageController = application.getImageTabController();
        long imageFileSize = imageController.getImgSize();
        try (FileInputStream sourceInputStream = new FileInputStream(sourceFile);
             FileOutputStream targetOutputStream = new FileOutputStream(f)) {
            sourceInputStream.skip(imageFileSize);
            // 根据ZIP文件头来识别并跳过图片部分
            // skipImagePartByZipHeader(sourceInputStream);
            // 写入剩余数据到目标文件（即原始ZIP文件）
            copyStream(sourceInputStream, targetOutputStream);
        }
    }

    /**
     * 根据ZIP文件头来识别并跳过文件开头的图片部分
     * ZIP文件头标识: 0x50 0x4B 0x03 0x04
     *
     * @param inputStream 输入流
     * @throws IOException IO异常
     */
    private void skipImagePartByZipHeader(FileInputStream inputStream) throws IOException {
        // ZIP文件头标识
        byte[] zipHeader = {0x50, 0x4B, 0x03, 0x04};
        byte[] buffer = new byte[1];

        // 用于存储已读取但不属于图片部分的字节（可能是ZIP文件头的一部分）
        byte[] tempBuffer = new byte[4];
        int tempIndex = 0;

        while (true) {
            int b = inputStream.read();
            if (b == -1) {
                // 到达文件末尾仍未找到ZIP文件头
                throw new IOException("未找到ZIP文件头");
            }

            // 将读取的字节添加到临时缓冲区
            tempBuffer[tempIndex] = (byte) b;
            tempIndex++;

            // 检查是否匹配ZIP文件头
            if (tempIndex == 4) {
                boolean isZipHeader = true;
                for (int i = 0; i < 4; i++) {
                    if (tempBuffer[i] != zipHeader[i]) {
                        isZipHeader = false;
                        break;
                    }
                }

                if (isZipHeader) {
                    // 找到ZIP文件头，将文件指针回退4个字节（即ZIP文件头的开始位置）
                    inputStream.getChannel().position(inputStream.getChannel().position() - 4);
                    break;
                } else {
                    // 不匹配，移动窗口：丢弃第一个字节，后面的字节前移
                    for (int i = 0; i < 3; i++) {
                        tempBuffer[i] = tempBuffer[i + 1];
                    }
                    tempIndex = 3;
                }
            }
        }
    }

    /**
     * 复制输入流到输出流
     *
     * @param input  输入流
     * @param output 输出流
     * @throws IOException IO异常
     */
    private void copyStream(FileInputStream input, FileOutputStream output) throws IOException {
        byte[] buffer = new byte[8192];
        int bytesRead;
        while ((bytesRead = input.read(buffer)) != -1) {
            output.write(buffer, 0, bytesRead);
        }
    }

    private void setupDragAndDrop() {
        decryptBox.setOnDragOver(event -> {
            if (event.getGestureSource() != decryptBox && event.getDragboard().hasFiles()) {
                event.acceptTransferModes(TransferMode.COPY_OR_MOVE);
            }
            event.consume();
        });

        decryptBox.setOnDragDropped(event -> {
            Dragboard dragboard = event.getDragboard();
            boolean success = false;
            if (dragboard.hasFiles()) {
                success = true;
                // 支持多文件或目录拖拽，但只使用第一个有效的文件

                files = dragboard.getFiles();
                for (File file : dragboard.getFiles()) {
                    sourceFileField.setText(file.getAbsolutePath());
                    break;
                }
            }
            event.setDropCompleted(success);
            event.consume();
        });
    }
}